package service

import (
	"context"
	"net/http"

	"github.com/mars/internal/admin/core/domain"
	"github.com/mars/pkg/errors"
	"github.com/mars/pkg/loggers"
)

type UserSrv interface {
	GetUserList(ctx context.Context) ([]domain.User, int64, error)
	GetUser(ctx context.Context, openid string) (*domain.User, error)
	CreateUser(ctx context.Context, user *domain.User) error
	UpdateUser(ctx context.Context, openid string, user *domain.User) error
	DeleteUser(ctx context.Context, openid string) error
	GetUsersByStatus(ctx context.Context, status string) ([]domain.User, error)
	GetVIPUsers(ctx context.Context) ([]domain.User, error)
	UpdateUserVIP(ctx context.Context, openid string, vipInfo *domain.VipInfo) error
}

type userService struct {
	userDomain domain.UserGateway
}

var _ UserSrv = (*userService)(nil)

func newUserService(fc domain.Factory) *userService {
	return &userService{
		userDomain: fc.UserDomain(),
	}
}

// GetUserList implements UserSrv.
func (u *userService) GetUserList(ctx context.Context) ([]domain.User, int64, error) {
	users, total, err := u.userDomain.Users(ctx)
	if err != nil {
		loggers.Error(ctx, "get user list failed", err)
		return nil, 0, errors.NewWithStackWithoutCode(http.StatusInternalServerError, "get user list failed")
	}
	return users, total, nil
}

// GetUser implements UserSrv.
func (u *userService) GetUser(ctx context.Context, openid string) (*domain.User, error) {
	user, err := u.userDomain.User(ctx, openid)
	if err != nil {
		loggers.Error(ctx, "get user failed", err)
		return nil, errors.NewWithStackWithoutCode(http.StatusInternalServerError, "get user failed")
	}
	return user, nil
}

// CreateUser implements UserSrv.
func (u *userService) CreateUser(ctx context.Context, user *domain.User) error {
	// 检查用户是否已存在（业务逻辑）
	existingUser, err := u.userDomain.User(ctx, user.OpenID)
	if err == nil && existingUser != nil {
		return errors.NewWithStackWithoutCode(http.StatusBadRequest, "user already exists")
	}

	err = u.userDomain.CreateUser(ctx, user)
	if err != nil {
		loggers.Error(ctx, "create user failed", err)
		return errors.NewWithStackWithoutCode(http.StatusInternalServerError, "create user failed")
	}
	return nil
}

// UpdateUser implements UserSrv.
func (u *userService) UpdateUser(ctx context.Context, openid string, user *domain.User) error {
	matched, err := u.userDomain.UpdateUser(ctx, openid, user)
	if err != nil {
		loggers.Error(ctx, "update user failed", err)
		return errors.NewWithStackWithoutCode(http.StatusInternalServerError, "update user failed")
	}
	if matched == 0 {
		return errors.NewWithStackWithoutCode(http.StatusBadRequest, "user not found")
	}
	return nil
}

// DeleteUser implements UserSrv.
func (u *userService) DeleteUser(ctx context.Context, openid string) error {
	// 检查用户是否存在（业务逻辑）
	_, err := u.userDomain.User(ctx, openid)
	if err != nil {
		loggers.Error(ctx, "user not found", err)
		return errors.NewWithStackWithoutCode(http.StatusInternalServerError, "user not found")
	}

	err = u.userDomain.DeleteUser(ctx, openid)
	if err != nil {
		loggers.Error(ctx, "delete user failed", err)
		return errors.NewWithStackWithoutCode(http.StatusInternalServerError, "delete user failed")
	}
	return nil
}

// GetUsersByStatus implements UserSrv.
func (u *userService) GetUsersByStatus(ctx context.Context, status string) ([]domain.User, error) {
	users, err := u.userDomain.GetUsersByStatus(ctx, status)
	if err != nil {
		loggers.Error(ctx, "get users by status failed", err)
		return nil, errors.NewWithStackWithoutCode(http.StatusInternalServerError, "get users by status failed")
	}
	return users, nil
}

// GetVIPUsers implements UserSrv.
func (u *userService) GetVIPUsers(ctx context.Context) ([]domain.User, error) {
	users, err := u.userDomain.GetVIPUsers(ctx)
	if err != nil {
		loggers.Error(ctx, "get VIP users failed", err)
		return nil, errors.NewWithStackWithoutCode(http.StatusInternalServerError, "get VIP users failed")
	}
	return users, nil
}

// UpdateUserVIP implements UserSrv.
func (u *userService) UpdateUserVIP(ctx context.Context, openid string, vipInfo *domain.VipInfo) error {
	matched, err := u.userDomain.UpdateUserVIP(ctx, openid, vipInfo)
	if err != nil {
		loggers.Error(ctx, "update user VIP failed", err)
		return errors.NewWithStackWithoutCode(http.StatusInternalServerError, "update user VIP failed")
	}
	if matched == 0 {
		return errors.NewWithStackWithoutCode(http.StatusBadRequest, "user not found")
	}
	return nil
}
